package model

import model.events.{
  BaseEvent,
  Confirmation,
  GroupJoin,
  GroupLeave,
  LikeAdd,
  LikeRemove,
  WallReplyNew,
  WallRepost
}
import zio.json.{JsonCodec, JsonDecoder, JsonEncoder}
import zio.json.*

enum EventTypeEnum(val name: String):
  case LikeAddType      extends EventTypeEnum("like_add")
  case ConfirmationType extends EventTypeEnum("confirmation")
  case LikeRemoveType   extends EventTypeEnum("like_remove")
  case GroupLeaveType   extends EventTypeEnum("group_leave")
  case GroupJoinType    extends EventTypeEnum("group_join")
  case WallReplyNewType extends EventTypeEnum("wall_reply_new")
  case WallRepostType   extends EventTypeEnum("wall_repost")

object EventTypeEnum {
  given JsonDecoder[EventTypeEnum] = JsonDecoder[String].map {
    // TODO: попробовать упростить
    case "confirmation"   => ConfirmationType
    case "like_add"       => LikeAddType
    case "like_remove"    => LikeRemoveType
    case "group_leave"    => GroupLeaveType
    case "group_join"     => GroupJoinType
    case "wall_reply_new" => WallReplyNewType
    case "wall_repost"    => WallRepostType
    case other            => throw new RuntimeException(s"Invalid event type: $other")
  }

  given JsonEncoder[EventTypeEnum] = JsonEncoder[String].contramap {
    case eventType: EventTypeEnum => eventType.name
    case _                        => throw new RuntimeException(s"Unknown event type")
  }

  given JsonCodec[EventTypeEnum] =
    JsonCodec(
      EventTypeEnum.given_JsonEncoder_EventTypeEnum,
      EventTypeEnum.given_JsonDecoder_EventTypeEnum
    )

  def parseByType(`type`: EventTypeEnum, body: String): Either[String, BaseEvent] = `type` match
    case LikeAddType      => body.fromJson[LikeAdd]
    case ConfirmationType => body.fromJson[Confirmation]
    case LikeRemoveType   => body.fromJson[LikeRemove]
    case GroupLeaveType   => body.fromJson[GroupLeave]
    case GroupJoinType    => body.fromJson[GroupJoin]
    case WallReplyNewType => body.fromJson[WallReplyNew]
    case WallRepostType   => body.fromJson[WallRepost]
}
